#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
香港各区疫情数据仪表板 - GUI版本
基于PyQt5的窗口化可视化操作软件
"""

import sys
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                             QHBoxLayout, QTabWidget, QPushButton, QLabel, 
                             QTextEdit, QFileDialog, QMessageBox, QProgressBar,
                             QGroupBox, QGridLayout, QTableWidget, QTableWidgetItem,
                             QSplitter, QFrame, QScrollArea)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QPixmap, QIcon, QPalette, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import pandas as pd
import numpy as np

# 导入自定义模块
from data_reader import EpidemicDataReader
from data_analyzer import EpidemicDataAnalyzer
from data_visualizer import EpidemicDataVisualizer

class DataProcessingThread(QThread):
    """数据处理线程"""
    progress_updated = pyqtSignal(int)
    status_updated = pyqtSignal(str)
    data_ready = pyqtSignal(object, object)
    
    def __init__(self, file_path):
        super().__init__()
        self.file_path = file_path
        
    def run(self):
        try:
            self.status_updated.emit("正在加载数据...")
            self.progress_updated.emit(10)
            
            # 数据读取
            reader = EpidemicDataReader(self.file_path)
            if reader.load_data():
                self.progress_updated.emit(30)
                self.status_updated.emit("正在读取工作表...")
                
                if reader.read_sheet(sheet_index=0):
                    self.progress_updated.emit(50)
                    self.status_updated.emit("正在分析数据...")
                    
                    # 数据分析
                    analyzer = EpidemicDataAnalyzer()
                    analyzer.set_data(reader.get_data())
                    
                    daily_stats = analyzer.calculate_daily_confirmed_cases()
                    regional_stats = analyzer.calculate_regional_stats()
                    
                    self.progress_updated.emit(80)
                    self.status_updated.emit("数据处理完成")
                    
                    # 发送数据
                    self.data_ready.emit(daily_stats, regional_stats)
                    self.progress_updated.emit(100)
                else:
                    self.status_updated.emit("读取工作表失败")
            else:
                self.status_updated.emit("加载数据失败")
                
        except Exception as e:
            self.status_updated.emit(f"处理失败: {str(e)}")

class MatplotlibWidget(QWidget):
    """Matplotlib图表组件"""
    def __init__(self, parent=None):
        super().__init__(parent)
        self.figure = Figure(figsize=(10, 6))
        self.canvas = FigureCanvas(self.figure)
        layout = QVBoxLayout()
        layout.addWidget(self.canvas)
        self.setLayout(layout)
        
    def plot_data(self, daily_stats, plot_type='daily_new'):
        """绘制数据图表"""
        self.figure.clear()
        ax = self.figure.add_subplot(111)
        
        if daily_stats is not None:
            if plot_type == 'daily_new':
                ax.plot(daily_stats['报告日期'], daily_stats['新增确诊'], 
                       color='#FF6B6B', linewidth=2, marker='o')
                ax.set_title('每日新增确诊病例', fontsize=14, fontweight='bold')
                ax.set_ylabel('新增确诊数')
            elif plot_type == 'total_confirmed':
                ax.plot(daily_stats['报告日期'], daily_stats['累计确诊'], 
                       color='#4ECDC4', linewidth=2, marker='s')
                ax.set_title('累计确诊病例', fontsize=14, fontweight='bold')
                ax.set_ylabel('累计确诊数')
            elif plot_type == 'current_cases':
                ax.plot(daily_stats['报告日期'], daily_stats['现存确诊'], 
                       color='#45B7D1', linewidth=2, marker='^')
                ax.set_title('现存确诊病例', fontsize=14, fontweight='bold')
                ax.set_ylabel('现存确诊数')
            elif plot_type == 'recovery_death':
                ax.plot(daily_stats['报告日期'], daily_stats['累计康复'], 
                       color='#96CEB4', linewidth=2, label='累计康复')
                ax.plot(daily_stats['报告日期'], daily_stats['累计死亡'], 
                       color='#FFEAA7', linewidth=2, label='累计死亡')
                ax.set_title('康复与死亡趋势', fontsize=14, fontweight='bold')
                ax.set_ylabel('人数')
                ax.legend()
            
            ax.grid(True, alpha=0.3)
            ax.tick_params(axis='x', rotation=45)
            
        self.canvas.draw()

class EpidemicDashboardGUI(QMainWindow):
    """疫情数据仪表板主窗口"""
    
    def __init__(self):
        super().__init__()
        self.daily_stats = None
        self.regional_stats = None
        self.init_ui()
        
    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle('香港各区疫情数据仪表板')
        self.setGeometry(100, 100, 1400, 900)
        
        # 设置窗口图标和样式
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
            }
            QTabWidget::pane {
                border: 1px solid #cccccc;
                background-color: white;
            }
            QTabBar::tab {
                background-color: #e1e1e1;
                padding: 8px 16px;
                margin-right: 2px;
            }
            QTabBar::tab:selected {
                background-color: #4CAF50;
                color: white;
            }
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
            QPushButton:pressed {
                background-color: #3d8b40;
            }
            QGroupBox {
                font-weight: bold;
                border: 2px solid #cccccc;
                border-radius: 5px;
                margin-top: 10px;
                padding-top: 10px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 5px 0 5px;
            }
        """)
        
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 创建标题
        title_label = QLabel('香港各区疫情数据仪表板')
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setStyleSheet("""
            QLabel {
                font-size: 24px;
                font-weight: bold;
                color: #2c3e50;
                padding: 20px;
                background-color: #ecf0f1;
                border-radius: 10px;
                margin: 10px;
            }
        """)
        main_layout.addWidget(title_label)
        
        # 创建控制面板
        self.create_control_panel(main_layout)
        
        # 创建标签页
        self.create_tabs(main_layout)
        
        # 创建状态栏
        self.statusBar().showMessage('就绪')
        
    def create_control_panel(self, main_layout):
        """创建控制面板"""
        control_group = QGroupBox("控制面板")
        control_layout = QHBoxLayout()
        
        # 文件选择按钮
        self.load_button = QPushButton("加载数据文件")
        self.load_button.clicked.connect(self.load_data_file)
        control_layout.addWidget(self.load_button)
        
        # 分析按钮
        self.analyze_button = QPushButton("开始分析")
        self.analyze_button.clicked.connect(self.start_analysis)
        self.analyze_button.setEnabled(False)
        control_layout.addWidget(self.analyze_button)
        
        # 导出按钮
        self.export_button = QPushButton("导出图表")
        self.export_button.clicked.connect(self.export_charts)
        self.export_button.setEnabled(False)
        control_layout.addWidget(self.export_button)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        control_layout.addWidget(self.progress_bar)
        
        # 状态标签
        self.status_label = QLabel("请选择数据文件")
        control_layout.addWidget(self.status_label)
        
        control_group.setLayout(control_layout)
        main_layout.addWidget(control_group)
        
    def create_tabs(self, main_layout):
        """创建标签页"""
        self.tab_widget = QTabWidget()
        
        # 概览标签页
        self.create_overview_tab()
        
        # 趋势分析标签页
        self.create_trend_tab()
        
        # 各区对比标签页
        self.create_regional_tab()
        
        # 数据详情标签页
        self.create_data_tab()
        
        main_layout.addWidget(self.tab_widget)
        
    def create_overview_tab(self):
        """创建概览标签页"""
        overview_widget = QWidget()
        layout = QVBoxLayout()
        
        # 统计信息组
        stats_group = QGroupBox("统计概览")
        stats_layout = QGridLayout()
        
        self.total_cases_label = QLabel("总确诊数: --")
        self.total_new_label = QLabel("总新增数: --")
        self.max_daily_label = QLabel("单日最高: --")
        self.recovery_rate_label = QLabel("康复率: --")
        self.death_rate_label = QLabel("死亡率: --")
        
        stats_layout.addWidget(self.total_cases_label, 0, 0)
        stats_layout.addWidget(self.total_new_label, 0, 1)
        stats_layout.addWidget(self.max_daily_label, 1, 0)
        stats_layout.addWidget(self.recovery_rate_label, 1, 1)
        stats_layout.addWidget(self.death_rate_label, 2, 0)
        
        stats_group.setLayout(stats_layout)
        layout.addWidget(stats_group)
        
        # 图表显示区域
        self.overview_chart = MatplotlibWidget()
        layout.addWidget(self.overview_chart)
        
        overview_widget.setLayout(layout)
        self.tab_widget.addTab(overview_widget, "概览")
        
    def create_trend_tab(self):
        """创建趋势分析标签页"""
        trend_widget = QWidget()
        layout = QVBoxLayout()
        
        # 图表选择按钮
        chart_buttons_layout = QHBoxLayout()
        
        self.daily_new_btn = QPushButton("每日新增")
        self.daily_new_btn.clicked.connect(lambda: self.show_trend_chart('daily_new'))
        chart_buttons_layout.addWidget(self.daily_new_btn)
        
        self.total_confirmed_btn = QPushButton("累计确诊")
        self.total_confirmed_btn.clicked.connect(lambda: self.show_trend_chart('total_confirmed'))
        chart_buttons_layout.addWidget(self.total_confirmed_btn)
        
        self.current_cases_btn = QPushButton("现存确诊")
        self.current_cases_btn.clicked.connect(lambda: self.show_trend_chart('current_cases'))
        chart_buttons_layout.addWidget(self.current_cases_btn)
        
        self.recovery_death_btn = QPushButton("康复死亡")
        self.recovery_death_btn.clicked.connect(lambda: self.show_trend_chart('recovery_death'))
        chart_buttons_layout.addWidget(self.recovery_death_btn)
        
        layout.addLayout(chart_buttons_layout)
        
        # 趋势图表
        self.trend_chart = MatplotlibWidget()
        layout.addWidget(self.trend_chart)
        
        trend_widget.setLayout(layout)
        self.tab_widget.addTab(trend_widget, "趋势分析")
        
    def create_regional_tab(self):
        """创建各区对比标签页"""
        regional_widget = QWidget()
        layout = QVBoxLayout()
        
        # 各区数据表格
        self.regional_table = QTableWidget()
        layout.addWidget(self.regional_table)
        
        regional_widget.setLayout(layout)
        self.tab_widget.addTab(regional_widget, "各区对比")
        
    def create_data_tab(self):
        """创建数据详情标签页"""
        data_widget = QWidget()
        layout = QVBoxLayout()
        
        # 数据详情文本区域
        self.data_text = QTextEdit()
        self.data_text.setReadOnly(True)
        layout.addWidget(self.data_text)
        
        data_widget.setLayout(layout)
        self.tab_widget.addTab(data_widget, "数据详情")
        
    def load_data_file(self):
        """加载数据文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择Excel文件", "", "Excel Files (*.xlsx *.xls)"
        )
        
        if file_path:
            self.file_path = file_path
            self.status_label.setText(f"已选择文件: {os.path.basename(file_path)}")
            self.analyze_button.setEnabled(True)
            
    def start_analysis(self):
        """开始数据分析"""
        if hasattr(self, 'file_path'):
            self.progress_bar.setVisible(True)
            self.progress_bar.setValue(0)
            
            # 创建并启动数据处理线程
            self.data_thread = DataProcessingThread(self.file_path)
            self.data_thread.progress_updated.connect(self.progress_bar.setValue)
            self.data_thread.status_updated.connect(self.status_label.setText)
            self.data_thread.data_ready.connect(self.on_data_ready)
            self.data_thread.start()
            
    def on_data_ready(self, daily_stats, regional_stats):
        """数据准备完成回调"""
        self.daily_stats = daily_stats
        self.regional_stats = regional_stats
        
        # 更新概览信息
        self.update_overview_stats()
        
        # 更新各区对比表格
        self.update_regional_table()
        
        # 更新数据详情
        self.update_data_details()
        
        # 显示默认图表
        self.overview_chart.plot_data(daily_stats, 'daily_new')
        
        # 启用导出按钮
        self.export_button.setEnabled(True)
        
        self.statusBar().showMessage('分析完成')
        
    def update_overview_stats(self):
        """更新概览统计信息"""
        if self.daily_stats is not None:
            total_cases = self.daily_stats['累计确诊'].iloc[-1]
            total_new = self.daily_stats['新增确诊'].sum()
            max_daily = self.daily_stats['新增确诊'].max()
            final_recovered = self.daily_stats['累计康复'].iloc[-1]
            final_deaths = self.daily_stats['累计死亡'].iloc[-1]
            
            recovery_rate = (final_recovered / total_cases * 100) if total_cases > 0 else 0
            death_rate = (final_deaths / total_cases * 100) if total_cases > 0 else 0
            
            self.total_cases_label.setText(f"总确诊数: {total_cases:,}")
            self.total_new_label.setText(f"总新增数: {total_new:,}")
            self.max_daily_label.setText(f"单日最高: {max_daily:,}")
            self.recovery_rate_label.setText(f"康复率: {recovery_rate:.1f}%")
            self.death_rate_label.setText(f"死亡率: {death_rate:.2f}%")
            
    def update_regional_table(self):
        """更新各区对比表格"""
        if self.regional_stats is not None:
            self.regional_table.setRowCount(len(self.regional_stats))
            self.regional_table.setColumnCount(6)
            self.regional_table.setHorizontalHeaderLabels([
                '地区名称', '累计确诊', '发病率(每10万人)', '康复率', '死亡率', '人口'
            ])
            
            for i, (_, row) in enumerate(self.regional_stats.iterrows()):
                self.regional_table.setItem(i, 0, QTableWidgetItem(str(row['地区名称'])))
                self.regional_table.setItem(i, 1, QTableWidgetItem(f"{row['累计确诊']:,}"))
                self.regional_table.setItem(i, 2, QTableWidgetItem(f"{row['发病率(每10万人)']:.2f}"))
                self.regional_table.setItem(i, 3, QTableWidgetItem(f"{row['康复率']:.1f}%"))
                self.regional_table.setItem(i, 4, QTableWidgetItem(f"{row['死亡率']:.2f}%"))
                self.regional_table.setItem(i, 5, QTableWidgetItem(f"{row['人口']:,}"))
                
    def update_data_details(self):
        """更新数据详情"""
        if self.daily_stats is not None:
            details = f"数据概览:\n"
            details += f"时间范围: {self.daily_stats['报告日期'].min().strftime('%Y-%m-%d')} 至 {self.daily_stats['报告日期'].max().strftime('%Y-%m-%d')}\n"
            details += f"总天数: {len(self.daily_stats)} 天\n"
            details += f"总新增确诊: {self.daily_stats['新增确诊'].sum():,} 例\n"
            details += f"累计确诊: {self.daily_stats['累计确诊'].iloc[-1]:,} 例\n"
            details += f"累计康复: {self.daily_stats['累计康复'].iloc[-1]:,} 例\n"
            details += f"累计死亡: {self.daily_stats['累计死亡'].iloc[-1]:,} 例\n\n"
            
            details += "前10天数据:\n"
            details += self.daily_stats.head(10).to_string()
            
            self.data_text.setText(details)
            
    def show_trend_chart(self, chart_type):
        """显示趋势图表"""
        if self.daily_stats is not None:
            self.trend_chart.plot_data(self.daily_stats, chart_type)
            
    def export_charts(self):
        """导出图表"""
        if self.daily_stats is not None:
            try:
                # 创建可视化器并导出图表
                visualizer = EpidemicDataVisualizer()
                visualizer.plot_daily_cases(self.daily_stats)
                
                if self.regional_stats is not None:
                    visualizer.plot_regional_comparison(self.regional_stats)
                    
                QMessageBox.information(self, "导出成功", "图表已成功导出到当前目录")
            except Exception as e:
                QMessageBox.critical(self, "导出失败", f"导出图表时发生错误: {str(e)}")

def main():
    """主函数"""
    app = QApplication(sys.argv)
    
    # 设置应用程序信息
    app.setApplicationName("香港疫情数据仪表板")
    app.setApplicationVersion("1.0")
    
    # 创建并显示主窗口
    window = EpidemicDashboardGUI()
    window.show()
    
    # 运行应用程序
    sys.exit(app.exec_())

if __name__ == "__main__":
    main() 